package com.atguigu.gmall.consumer;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.Service.OrderInfoService;
import com.atguigu.gmall.client.service.PaymentFeignClientService;
import com.atguigu.gmall.constant.MqConst;
import com.atguigu.gmall.entity.OrderDetail;
import com.atguigu.gmall.entity.OrderInfo;
import com.atguigu.gmall.entity.PaymentInfo;
import com.atguigu.gmall.enums.OrderStatus;
import com.atguigu.gmall.enums.PaymentStatus;
import com.atguigu.gmall.enums.ProcessStatus;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class OrderConsumer {

    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private PaymentFeignClientService paymentFeignClientService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /*时间到了检查订单状态，如果未支付，删除订单*/
    @RabbitListener(queues = MqConst.CANCEL_ORDER_QUEUE)
    public void cancelOrder(Long orderId, Message message, Channel channel) throws Exception {
        //获取订单的信息
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        if (ObjectUtils.isEmpty(orderInfo)){
            return;//订单为空，
        }
        //如果订单为未支付状态
        if (orderInfo.getOrderStatus().equals(ProcessStatus.UNPAID.getOrderStatus().name())) {
            //关闭订单信息
            orderInfoService.updateOrderStatus(orderInfo.getId(), ProcessStatus.CLOSED);
            //根据交易流水号获取支付订单
            PaymentInfo paymentInfo = paymentFeignClientService.getPaymentInfo(orderInfo.getOutTradeNo());
            //如果有支付订单信息
            if (paymentInfo != null && paymentInfo.getPaymentStatus().equals(PaymentStatus.UNPAID.name())) {
                rabbitTemplate.convertAndSend(MqConst.CLOSE_PAYMENT_EXCHANGE, MqConst.CLOSE_PAYMENT_ROUTE_KEY, orderId);
                //如果阿里系统创建了交易 则关闭阿里内部交易
                boolean flag = paymentFeignClientService.queryAlipayTrade(orderId);
                if (flag) {
                    paymentFeignClientService.closeAlipayTrade(orderId);
                }
            }
        }
        /*手动确认，需要配置*/
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }


    //监听修改订单的队列
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.PAY_ORDER_EXCHANGE, durable = "false"),
            key = {MqConst.PAY_ORDER_ROUTE_KEY},
            value = @Queue(value = MqConst.PAY_ORDER_QUEUE, durable = "false")
    ))
    public void updateOrderStatus(Long orderId, Message message, Channel channel) throws IOException {
        //更新订单支付状态为已支付
        orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);
        //更新库存信息
        OrderInfo orderInfo = orderInfoService.findOrderById(orderId); //先获取订单详情
        Map<String, Object> map = this.assembleWareHouseData(orderInfo);
        String orderTaskJson = JSONObject.toJSONString(map);//把orderInfo改为json串

        rabbitTemplate.convertAndSend(MqConst.DECREASE_STOCK_EXCHANGE, MqConst.DECREASE_STOCK_ROUTE_KEY,orderTaskJson);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);//手动应答
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.SUCCESS_DECREASE_STOCK_EXCHANGE, durable = "false"),
            key = {MqConst.SUCCESS_DECREASE_STOCK_ROUTE_KEY},
            value = @Queue(value = MqConst.SUCCESS_DECREASE_STOCK_QUEUE, durable = "false")
    ))
    public void updateOrderStatusAfterDecreaseStock(String msgStr, Message message, Channel channel) throws IOException {
        if (!StringUtils.isEmpty(msgStr)){
            Map map = JSONObject.parseObject(msgStr, Map.class);//获取数据
            Long orderId = (Long) map.get("orderId");
            String status = (String) map.get("status");
            if ("DEDUCTED".equals(status)){
                //修改订单的状态,代发货
                orderInfoService.updateOrderStatus(orderId,ProcessStatus.WAITING_DELEVER);
            }else {
                orderInfoService.updateOrderStatus(orderId,ProcessStatus.STOCK_EXCEPTION); //库存异常
            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    private Map<String, Object> assembleWareHouseData(OrderInfo orderInfo) {
        //先构造一个map
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderId",orderInfo.getId());
        dataMap.put("consignee",orderInfo.getConsignee());
        dataMap.put("consigneeTel",orderInfo.getConsigneeTel());
        dataMap.put("orderComment",orderInfo.getOrderComment());
        dataMap.put("orderBody",orderInfo.getTradeBody());
        dataMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        dataMap.put("paymentWay",2);
        //TODO 这里要添加一个非常重要的字段
        dataMap.put("wareId",orderInfo.getWareHouseId());
        //商品清单
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //把商品清单放入一个list集合里面
        List<Map> orderDetailMapList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            Map<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            orderDetailMapList.add(orderDetailMap);
        }
        dataMap.put("details",orderDetailMapList);
        return dataMap;
    }
}